<?php

namespace App\Http\Controllers;

use App\Http\Traits\CacheTrait;
use App\Http\Traits\GitLabTrait;
use App\Models\RepoSetting;
use Illuminate\Http\Request;
use Validator;

class ProjectController extends Controller
{
    use CacheTrait, GitLabTrait;

    private $gitlab_client;

    public function __construct()
    {
        $this->gitlab_client = $this->getGitLab();
    }

    public function show(Request $request, $project_id)
    {
        $project = $this->gitlab_client->projects->show($project_id);

        $setting_list = RepoSetting::where('repo_id', $project_id)->get();
        if ($request->isXmlHttpRequest()) {
            return response(['setting_list' => $setting_list, 'project' => $project]);
        } else {
            return view('project.show')->with(['setting_list' => $setting_list, 'project' => $project]);
        }
    }

    public function branches(Request $request, $project_id)
    {
        if ($request->isXmlHttpRequest()) {
            $branches = $this->getBranches($project_id);
            $tags     = $this->getTags($project_id);

            usort($tags, function ($tag1, $tag2) {
                if (strtotime($tag1['commit']['created_at']) == strtotime($tag2['commit']['created_at'])) {
                    return 0;
                }

                if (strtotime($tag1['commit']['created_at']) < strtotime($tag2['commit']['created_at'])) {
                    return 1;
                }

                return -1;
            });
            $tags = array_splice($tags, 0, 10);

            return response(['branches' => $branches, 'tags' => $tags]);
        }

        return response([]);
    }

    public function remove($project_id, $setting_id)
    {
        $result = RepoSetting::where(['repo_id' => $project_id, 'id' => $setting_id])->delete();

        if ($result) {
            return back()->with(['success_msg' => '删除成功']);
        }

        return back()->with(['error_msg' => '删除失败']);
    }

    public function edit($project_id, $setting_id)
    {
        $project  = $this->gitlab_client->projects->show($project_id);
        $branches = $this->gitlab_client->repositories->branches($project_id);
        /*$tags     = $this->gitlab_client->repositories->tags($project_id);
        var_dump($tags);*/

        $repo_setting = RepoSetting::where(['repo_id' => $project_id])->find($setting_id);

        $repo_namespace   = $project['path_with_namespace'];
        $repo_id          = $repo_setting->repo_id;
        $repo_url         = $repo_setting->repo_url;
        $repo_name        = $project['name'];
        $app_path         = $repo_setting->app_path;
        $app_logs_path    = $repo_setting->app_logs_path;
        $app_configs_path = $repo_setting->app_configs_path;
        $ssh_host         = $repo_setting->ssh_host;
        $server_env       = $repo_setting->server_env;
        $default_branch   = $repo_setting->default_branch;
        $setting_name     = $repo_setting->name;
        $exclude_files    = $repo_setting->exclude_files;

        return view('project.edit')->with([
            'project'      => compact('repo_namespace', 'repo_name'),
            'branches'     => $branches,
            'repo_setting' => compact('setting_name', 'setting_id', 'repo_url', 'repo_id', 'app_path', 'app_logs_path', 'app_configs_path', 'ssh_host', 'server_env', 'default_branch', 'exclude_files'),
        ]);
    }

    public function update(Request $request, $setting_id)
    {
        $validator = Validator::make($request->all(), [
            'name'           => 'required|string',
            'ssh_host'       => 'required|string',
            'repo_url'       => 'required|url',
            'app_path'       => 'required|string',
            'server_env'     => 'required|string',
            'repo_id'        => 'required|integer',
            'default_branch' => 'required|string',
        ]);

        if ($validator->fails()) {
            return back()->withErrors($validator)->withInput();
        }

        $data = $request->only(['name', 'ssh_host', 'repo_url', 'app_path', 'repo_id', 'app_logs_path', 'app_configs_path', 'server_env', 'default_branch', 'exclude_files']);

        if (RepoSetting::where('id', $setting_id)->update($data)) {
            return back()->with(['success_msg' => '修改配置成功']);
        }

        return back()->withErrors('修改配置失败')->withInput();
    }

    public function cloneSetting($project_id, $setting_id)
    {
        $setting = RepoSetting::where(['repo_id' => $project_id])->find($setting_id);
        unset($setting->id, $setting->created_at, $setting->updated_at);
        $result = RepoSetting::create($setting->toArray());
        if ($result) {
            return back()->with(['success_msg' => '克隆成功']);
        }

        return back()->with(['error_msg' => '克隆失败']);
    }

    public function save(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'name'           => 'required|string',
            'ssh_host'       => 'required|string',
            'repo_url'       => 'required|url',
            'app_path'       => 'required|string',
            'server_env'     => 'required|string',
            'repo_id'        => 'required|integer',
            'default_branch' => 'required|string',
        ]);

        if ($validator->fails()) {
            return back()->withErrors($validator)->withInput();
        }

        $data = $request->only(['name', 'ssh_host', 'repo_url', 'app_path', 'repo_id', 'app_logs_path', 'app_configs_path', 'server_env', 'default_branch', 'exclude_files']);

        if (RepoSetting::create($data)) {
            return back()->with(['success_msg' => '创建成功']);
        }

        return back()->withErrors('部署配置失败')->withInput();
    }

    public function create($project_id)
    {
        $project  = $this->gitlab_client->projects->show($project_id);
        $branches = $this->gitlab_client->repositories->branches($project_id);

        if ($project) {
            $repo_namespace   = $project['path_with_namespace'];
            $repo_id          = $project['id'];
            $repo_url         = $this->getRealRepoUrl($repo_namespace);
            $repo_name        = $project['name'];
            $app_path         = '/data/wwwroot/service_' . $repo_name;
            $app_logs_path    = '/data/deploy/' . $repo_name . '/logs';
            $app_configs_path = '/data/deploy/' . $repo_name . '/(.env|Conf)/';

            return view('project.create')->with([
                'app'      => compact('app_path', 'app_logs_path', 'app_configs_path'),
                'project'  => compact('repo_namespace', 'repo_url', 'repo_name', 'repo_id'),
                'branches' => $branches,
            ]);
        }

        return back();
    }
}
